/*
Copyright (C) 1999
For non-commercial use only.

File	: tga.c
Date	: 05/05/1999
Author	: Nate Miller
Contact	: vandals1@home.com

Change Log
**********
7/26/99 - added code to fclose () a file when there is an error
6/11/99 - added support for 8bit images, changed commenting
*/

//Modified for glfu

#include <glf.h>
#include <glfu.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/*
=============
getRGBA

Reads in RGBA data for a 32bit image. 
=============
*/
unsigned char *getRGBA (FILE *s, int size)
{
	unsigned char *rgba;
	unsigned char temp;
	int bread;
	int i;

	rgba = ( malloc (size * 4) ); 

	if (rgba == NULL)
		return 0;

	bread = fread (rgba, sizeof (unsigned char), size * 4, s); 

	/* TGA is stored in BGRA, make it RGBA */
	if (bread != size * 4)
	{
		free (rgba);
		return 0;
	}

	for (i = 0; i < size * 4; i += 4 )
	{
		temp = rgba[i];
		rgba[i] = rgba[i + 2];
		rgba[i + 2] = temp;
	}

	return rgba;
}
/*
=============
getRGB

Reads in RGB data for a 24bit image. 
=============
*/
unsigned char *getRGB (FILE *s, int size)
{
	unsigned char *rgb;
	unsigned char temp;
	int bread;
	int i;

	rgb = ( malloc (size * 3) ); 

	if (rgb == NULL)
		return 0;

	bread = fread (rgb, sizeof (unsigned char), size * 3, s);

	if (bread != size * 3)
	{
		free (rgb);
		return 0;
	}

	/* TGA is stored in BGR, make it RGB */
	for (i = 0; i < size * 3; i += 3)
	{
		temp = rgb[i];
		rgb[i] = rgb[i + 2];
		rgb[i + 2] = temp;
	}

	return rgb;
}
/*
=============
getGray

Gets the grayscale image data.  Used as an alpha channel.
=============
*/
unsigned char *getGray (FILE *s, int size)
{
	unsigned char *grayData;
	int bread;

	grayData = ( malloc (size) );

	if (grayData == NULL)
		return 0;

	bread = fread (grayData, sizeof (unsigned char), size, s);

	if (bread != size)
	{
		free (grayData);
		return 0;
	}

	return grayData;
}
/*
=============
getData

Gets the image data for the specified bit depth.
=============
*/
unsigned char *getData (FILE *s, int sz, int iBits )
{
	if (iBits == 32)
	{
		return getRGBA( s, sz );
	}
	else if (iBits == 24)
	{
		return getRGB( s, sz );
	}
	else if (iBits == 8)
	{
		return getGray( s, sz );
	}
	assert( 0 );
	return 0;
}

/*
=============
loadTGA

Loads up a targa file.  Supported types are 8,24 and 32 uncompressed images.  
id is the texture ID to bind too.
=============
*/
int glfuLoadTextureData2dTga( glfuTextureData2d_t *data, const char *filename )
{
	GLenum texFormat = 0;
	unsigned char type[4];
	unsigned char info[7];
	unsigned char *imageData = NULL;
	int imageWidth, imageHeight;
	int imageBits, size;
	FILE *s;

	if (!(s = fopen (filename, "rb")))
		return -1;

	fread (&type, sizeof (char), 3, s); // read in colormap info and image type, byte 0 ignored
	fseek (s, 12, SEEK_SET);			// seek past the header and useless info
	fread (&info, sizeof (char), 6, s);

	if (type[1] != 0 || (type[2] != 2 && type[2] != 3))
		return -1;

	imageWidth = info[0] + info[1] * 256; 
	imageHeight = info[2] + info[3] * 256;
	imageBits =	info[4]; 

	size = imageWidth * imageHeight; 

	switch( imageBits )
	{
	case 32:
		texFormat = GL_RGBA;
		break;
	case 24:
		texFormat = GL_RGB;
		break;
	case 8:
		texFormat = GL_ALPHA;
		break;
	default:
		return -1;
	}

	imageData = getData (s, size, imageBits );

	/* no image data */
	if (imageData == NULL)
		return -1;

	fclose (s);

	data->width = imageWidth;
	data->height = imageHeight;
	data->format = texFormat;
	data->data = imageData;
	data->size = size;

	return 0;
}

